package cn.springbak.publish.Service.aspect;

import cn.springbak.publish.Service.SysLogService;
import cn.springbak.publish.common.annotation.RequiredLog;
import cn.springbak.publish.pojo.SysLog;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Order(3)
@Slf4j
@Aspect
@Component
public class SysLogAspect {
    @Pointcut("@annotation(cn.springbak.publish.common.annotation.RequiredLog)")
    public void doLog(){}
    public Object doLogAround(ProceedingJoinPoint joinPoint) throws Throwable{
        long t1 = System.currentTimeMillis();
        log.info("before {}", t1);
        try{
            Object result = joinPoint.proceed();
            long t2 = System.currentTimeMillis();
            log.info("after {}", t2);
            doLogInfo(joinPoint, (t2-t1), null);
            return result;
        }catch(Throwable e){
            e.printStackTrace();
            long t3 = System.currentTimeMillis();
            log.error("exception {}", t3);
            doLogInfo(joinPoint, (t3-t1), e);
            throw e;
        }
    }
    /*
    @Pointcut("@annotation(cn.springbak.publish.common.annotation.RequiredLog)")
    public void doLog(){}//此方法只负责承载切入点，不需要写方法实现
    @Around("doLog()")//@Around("@cn.springbak.publish.common.annotation(cy.pj.common.cn.springbak.publish.common.annotation.RequiredLog)")
    public Object doLogAround(ProceedingJoinPoint joinPoint)
            throws Throwable{
        System.out.println("SysLogAspect.@Around.before");
        long t1= System.currentTimeMillis();
        log.info("before {}",t1);
        try {
            Object result = joinPoint.proceed();//调用切入点方法
            long t2=System.currentTimeMillis();
            log.info("after {}",t2);
            doLogInfo(joinPoint,(t2-t1),null);
            return result;//此返回值会交给代理对象，代理对象传给调用方法
        }catch(Throwable e){
            e.printStackTrace();
            long t3=System.currentTimeMillis();
            log.error("exception {}",t3);
            //记录详细的异常行为日志
            doLogInfo(joinPoint,(t3-t1),e);
            throw e;
        }
    }*/
    private void doLogInfo(ProceedingJoinPoint joinPoint,long time,Throwable e) throws Exception{
        String username = "tony";
        Class<?> targetCls = joinPoint.getTarget().getClass();
        Signature signature = joinPoint.getSignature();
        MethodSignature ms = (MethodSignature) signature;
        Method targetMethod = targetCls.getDeclaredMethod(ms.getName()ms.getParameterTypes());
        RequiredLog requiredLog = targetMethod.getAnnotation(RequiredLog.class);
        String operation = requiredLog.operation();
        String targetClsMethod = targetCls.getName()+"."+targetMethod.getName();
        Object[] args = joinPoint.getArgs();
        String jsonParamStr = new ObjectMapper().writeValueAsString(args);
        SysLog userLog = new SysLog();
        userLog.setUsername(username);
        userLog.setIp("10.2.3.4");
        userLog.setOperation(operation);
        userLog.setMethod(targetClsMethod);
        userLog.setParams(jsonParamStr);
        if(e != null){
            userLog.setStatus(0);
            userLog.setError(e.getMessage());
        }
        userLog.setTime(time);
        log.info("usr.oper {}", new ObjectMapper().writeValueAsString(userLog));
        sysLogService.saveLog(userLog);
    }
    /*
    private void doLogInfo(ProceedingJoinPoint joinPoint,long time,Throwable e)
            throws Exception {
        String username = "tony";
        String ip = "202.106.29.20";
        Class<?> targetCls = joinPoint.getTarget().getClass();
        Signature signature = joinPoint.getSignature();
        MethodSignature ms = (MethodSignature) signature;
        Method targetMethod =
                targetCls.getDeclaredMethod(ms.getName(), ms.getParameterTypes());
        RequiredLog requiredLog = targetMethod.getAnnotation(RequiredLog.class);
        String operation = requiredLog.operation();
        String targetClsMethod = targetCls.getName() + "." + targetMethod.getName();
        Object[] args = joinPoint.getArgs();
        String jsonParamStr = new ObjectMapper().writeValueAsString(args);
        SysLog userLog = new SysLog();
        userLog.setUsername(username);
        userLog.setIp(ip);
        userLog.setOperation(operation);
        userLog.setMethod(targetClsMethod);
        userLog.setParams(jsonParamStr);
        if (e != null) {
            userLog.setStatus(0);//操作状态
            userLog.setError(e.getMessage());//错误信息
        }
        userLog.setTime(time);
        log.info("user.oper {}", new ObjectMapper().writeValueAsString(userLog));
        sysLogService.saveLog(userLog);
    }*/
    @Autowired
    private SysLogService sysLogService;

}
